<?php
namespace GrouppaGroup;

/**
 * A class for handling connections to database
 * Access through getInstance()
 * @author Sylwester Kogowski
 *
 */
class Db
{
    /**
     * instance of this class
     * @var Db
     */
    private static $instance = null;

    /**
     * Gets a (new or if possible - old) instance of connection to the database
     * @return Db         instance of the connection to the database
     * @throws \Exception if the connection couldn't be estabilished
     */
    public static function getInstance()
    {
        //CHECK: get instance to mysql
        if (self::$instance == null) {
            self::$instance = new Db();
        }

        return self::$instance;
    }

    /**
     * gets number of affected rows in last database  UPDATE operation
     * limited to 9
     */
    public function getAffectedRows()
    {
        return $this->dbConnection->info[26] - 0x30;
    }

    /**
     * gets id assigned during last insert operation
     */
    public function getLastId()
    {
        return $this->lastInsertId;
    }
    /**
     * checks if last insertion function succeeded
     * @return boolean true iff succeeded
     */
    public function getInserted()
    {
        if (!$this->dbConnection->info)
            return $this->dbConnection->insert_id >= 0;
        return $this->dbConnection->info[9] > 0;
    }

    /**
     * contains connection to mysql server
     * @var mysqli
     */
    private $dbConnection;

    public function escape($text)
    {
        return $this->dbConnection->real_escape_string($text);
    }


    /**
     * hidden constructor, use getInstance()
     * @throws \Exception if the connection couldn't be estabilished
     */
    private function __construct()
    {
        //CHECK: initialize connection to mysql
        $this->dbConnection = new \mysqli(DB_URL, DB_USER_NAME, DB_USER_PASSWORD,
            DB_DB_NAME);
        if ($this->dbConnection->connect_errno) { //error with the connection
            throw new \Exception('Couldn\'t connect to database: ' . $this->dbConnection->
                connect_error);
        }
        $this->dbConnection->set_charset('utf8');
    }

    /**
     * Send a query to the server
     * @param  string         $query
     * @throws \Exception     if the query wasn't sent successfully
     * @return \mysqli_result result of the query:<br/>
     *                              in case of queries it will be <b>\mysqli_result</b>, remember to free it after use!<br/>
     *                              in case of insertions/updates it will be <b>boolean</b><br/>
     */
    public function sendQuery($query)
    {
        //CHECK: send a query to the server
        $result = $this->dbConnection->query($query);
        if (!$result) {
            throw new \Exception('Error while sending query (' . $query .
                ') to the database: ' . $this->dbConnection->error);
        }

        return $result;
    }

    private $lastInsertId;
    /**
     * Send an insert query to the server
     * @param  string     $query with insert sql statement
     * @param  string     $table table for insertion
     * @throws \Exception if the query wasn't sent successfully
     * @return boolean    result of the query:<br/>
     *                          true iff insertion succeeded
     */
    public function sendInsertQuery($query, $table)
    {
        $this->lastInsertId = self::getAutoIncrementValue($table);
        //CHECK: send a query to the server
        $result = $this->dbConnection->query($query);

        return $result;
    }

    /**
     * Send an update query to the server
     * @param  string     $query with update sql statement
     * @throws \Exception if the query wasn't sent successfully
     * @return integer    result of the query:<br/>
     *                          how many rows were updated
     */
    public function sendUpdateQuery($query)
    {
        //CHECK: send a query to the server
        $this->dbConnection->query($query);

        return $this->dbConnection->affected_rows;
    }


    /**
     * Send an replace query to the server
     * @param  string     $query with update sql statement
     * @throws \Exception if the query wasn't sent successfully
     * @return boolean    result of the query:<br/>
     *                          true if replace updated at least one row
     */
    public function sendReplaceQuery($query)
    {
        //CHECK: send a query to the server
        $result = $this->dbConnection->query($query);

        return $result;
    }
    public static function getAutoIncrementValue($table)
    {
        $result = Db::getInstance()->sendQuery("SHOW TABLE STATUS LIKE '$table';");
        $row = $result->fetch_assoc();

        return $row['Auto_increment'];
    }
}
